#include "stdafx.h"

#include "globals.h"
#include "../../Common/Virtual.h"
#include "FilterControl.H"
#include <atlbase.h>


#ifdef VPU_CLOCK_CONTROL
#include "iTccVPUControl.h"
#endif

const int MAX_VOLUMES = 16;

static LONG s_volume_values[MAX_VOLUMES] = { // increment 6db..
	-10000, -5754, -3311, -1905, -1300, 
	-1000, -900, -800, -700, -600,
	-500, -400, -300, -200, -100, 
	0
};

CFilterControl cNewFilterCtrl;

CFilterControl::CFilterControl()
: mLCDImage(0)
#ifdef __MULTIDISPLAY__
, mpDuplicator(NULL)
#endif
, mPrimaryRendererLCDC(1)
, mPrimaryRendererImage(0)
, mbSeconldyRenderer(false)
, mSecondlyRendererLCDC(1)
, mSecondlyRendererImage(2)
{
	mpGraph = NULL;
#ifdef __EC_COMPLETE_INCLUDE__
	m_pMex = NULL;
#endif
#ifdef __FILTER_SPEED_CONTROL__
	m_pMediaSeeking =NULL;
	m_nIndex = 0;
#endif

#ifdef VPU_CLOCK_CONTROL
	mVpuDec = NULL;
#endif

#ifdef TCCAUDIO_SELECT
	m_pAVIDemuxer=NULL;
#endif

	mpCaptionParser = NULL;
	mpCaptionRenderer = NULL;
	mpCDKDemux_forInnerSub = NULL;

	m_nType = -1;
	m_bSetRegistry = FALSE;
}

CFilterControl::~CFilterControl()
{
}

BOOL CFilterControl::CheckCoCreateInstance(HRESULT &hr, REFCLSID rclsid, REFIID riid, LPVOID* ppv, LPCTSTR pszErrorMessage)
{
	if( SUCCEEDED(hr) )
	{
		hr=::CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, riid, ppv);
		if( SUCCEEDED(hr) )
		{
			return TRUE;
		}
		else
		{
			TCHAR tmp[256];
			::wsprintf(tmp, TEXT("[FAIL]CoCreateInstance(%x%x%x%x), %s"), ((DWORD *)&rclsid)[0], ((DWORD *)&rclsid)[1], ((DWORD *)&rclsid)[2], ((DWORD *)&rclsid)[3], pszErrorMessage);
			
			::MessageBox(NULL, tmp, TEXT("TCCAMManger"), 0);
			::printf("[FAIL]CoCreateInstance(%x%x%x%x) hr=%x\r\n", ((DWORD *)&rclsid)[0], ((DWORD *)&rclsid)[1], ((DWORD *)&rclsid)[2], ((DWORD *)&rclsid)[3], hr);
		}
	}

	return FALSE;
}

int CFilterControl::CreateFilterGraph(void)
{
	//printf("[CFilterControl::CreateFilterGraph]\n");

	HRESULT hr=S_OK;

	CoInitialize(NULL);

	CheckCoCreateInstance(hr, CLSID_FilterGraph, IID_IGraphBuilder, (void **)&mpGraph, TEXT("CLSID_FilterGraph fail"));	

	if( SUCCEEDED(hr) )
	{
		// DEQ Filter Create
		hr=S_OK;	
#ifdef __TCC_AUDIO_OUTPUT_CONTROL_FILTER__
		hr = CoCreateInstance((REFCLSID)CLSID_TCCAudioOutputControlFilter, NULL, CLSCTX_INPROC, (REFIID)IID_IBaseFilter,
			(void**)&m_pTCCAudioOutputControlFilter);

		if (SUCCEEDED(hr))
		{
			hr = mpGraph->AddFilter(m_pTCCAudioOutputControlFilter, L"TCC Audio Output Control Filter");
		}
#endif
#ifdef __FILTER_SPEED_CONTROL__		
		mpGraph->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
		if(m_pMC)
		{
			m_pMC->QueryInterface(IID_IMediaSeeking, (void **)&m_pMediaSeeking);
		}
		else
			printf("ERROR: m_pMC=NULL\r\n");
#endif
		return 1;
	}
	
	return 0;	
}


void CFilterControl::DestroyFilterGraph(void)
{
	//printf("[DestroyFilterGraph]Start\n");
#ifdef TCCAUDIO_SELECT	
	SAFE_RELEASE(m_pAVIDemuxer);
#endif	

	SAFE_RELEASE(mpCDKDemux_forInnerSub);

#ifdef __EC_COMPLETE_INCLUDE__
	SAFE_RELEASE(m_pMex);
#endif
#ifdef __FILTER_SPEED_CONTROL__
	SAFE_RELEASE(m_pMC);
	SAFE_RELEASE(m_pMediaSeeking);
#endif

#ifdef __TCC_AUDIO_OUTPUT_CONTROL_FILTER__
	SAFE_RELEASE(m_pTCCAudioOutputControlFilter);
#endif
	mpGraph->AddRef();
	int iRetFilterValue=mpGraph->Release();
	if(iRetFilterValue>1)
	{
		printf("\t\t DestroyFilterGraph::RemindRef=%d\n",iRetFilterValue);
	}

	SAFE_RELEASE(mpGraph);

	CoUninitialize();	

	//printf("[DestroyFilterGraph]End\n");
}


////////////////////////////////////////////////////////////////////////////////////////////////////

HRESULT CFilterControl::RunGraph()
{
	if (!mpGraph)
		return FALSE;

	IMediaControl* p_mc = NULL;

	HRESULT hr = mpGraph->QueryInterface(IID_IMediaControl, (void **)&p_mc);
	if (hr == S_OK)
	{
		hr = p_mc->Run();
		
		if (SUCCEEDED(hr))
		{
			mIsRunning = TRUE;
			printf("[CFilterControl::RunGraph]Succeed RunGraph\r\n");
		}
		else
		{
			printf("[CFilterControl::RunGraph]Fail : RunGraph(ret=0x%x)\r\n", hr);
		}

		SAFE_RELEASE(p_mc);
	}

	return hr;
}

//
// Stop the graph
// -- (return ) TRUE, if successful / FALSE, otherwise
//
BOOL CFilterControl::StopGraph()
{
	if (!mpGraph)
		return FALSE;
	
	if (mIsRunning)
	{
		IMediaControl* p_mc = NULL;
		HRESULT hr = mpGraph->QueryInterface(IID_IMediaControl, (void **)&p_mc);
		if (hr == S_OK)
		{
			hr = p_mc->Stop();			
			if (SUCCEEDED(hr))
			{
				mIsRunning = FALSE;
				printf("[CFilterControl::StopGraph]Succeed to stop Graph\n");
			}
			else
			{
				printf("[CFilterControl::StopGraph]Fail : StopGraph 0x%x\n", hr);
			}				

			SAFE_RELEASE(p_mc);
		}
		else
		{
			printf("[CFilterControl::StopGraph]Fail : mpGraph->QueryInterface(IID_IMediaControl)\n");
		}

		return SUCCEEDED(hr);
	}
	else
		printf("StopGraph(SKIPPED) since it's already stopped\r\n");

	return FALSE;
}

//
// Pause the graph
// -- (return ) TRUE, if successful / FALSE, otherwise
//
BOOL CFilterControl::PauseGraph()
{
	if (!mpGraph)
		return FALSE;
	
	IMediaControl* p_mc = NULL;
	HRESULT hr = mpGraph->QueryInterface(IID_IMediaControl, (void **)&p_mc);
	if( hr==S_OK )
	{
		hr = p_mc->Pause();
		
		if (SUCCEEDED(hr))
		{
			mIsRunning = TRUE;
		}
		else
		{
			printf("[CFilterControl::PauseGraph]Fail : PauseGraph(ret=0x%x)\r\n", hr);
		}
		SAFE_RELEASE(p_mc);
	}

	return SUCCEEDED(hr);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
static const GUID CLSID_TCCCAPTIONPARSER =
{0xf52bdb25, 0xe177, 0x4f29, 0x9d, 0x7a, 0x3d, 0x9f, 0x54, 0xbc, 0x91, 0x66};

#if 0
static const GUID CLSID_TCCCAPTIONRENDERER = 
{0x36a563c1, 0x254e, 0x4d0d, { 0x85, 0xc6, 0x6e, 0x9c, 0xc3, 0xf5, 0xa6, 0xba } };
#else
// {61C4E71C-8BC4-40d1-B2B1-18FFA7F8BF94}
///static const GUID CLSID_TCCSubtitleRenderer={0x61c4e71c, 0x8bc4, 0x40d1, { 0xb2, 0xb1, 0x18, 0xff, 0xa7, 0xf8, 0xbf, 0x94}};
static const GUID CLSID_TCCCAPTIONRENDERER={0x61c4e71c, 0x8bc4, 0x40d1, { 0xb2, 0xb1, 0x18, 0xff, 0xa7, 0xf8, 0xbf, 0x94}};
#endif


TCHAR CaptionExtension[E_DIVX_CAPTION_MAX][4] = { L"smi", L"srt", L"sub", L"ssa" };

int CFilterControl::CreateFilterForPlaying(TCHAR *FileName, CRect OutputSize, HWND hWnd, CaptionRenderInfo CaptionInfo)
{
	//printf("[CFilterControl::CreateFilterForPlaying]\n");

	HRESULT hr=S_OK;

	TCHAR *pDest;
	int iFileType, iResult;

//	DestroyFilterGraph();

	CreateFilterGraph();

#ifdef __MULTIDISPLAY__
    CheckCoCreateInstance(hr, CLSID_TCVideoDuplicator, IID_IBaseFilter, (void **)&mpDuplicator, TEXT("CLSID_TCVideoDuplicator fail"));
    ITCVideoDuplicator *pDuplicator=NULL;
    if( SUCCEEDED(mpDuplicator->QueryInterface(IID_ITCVideoDuplicator, (void **)&pDuplicator)) )
    {
        pDuplicator->SetOutputPinCount(2);

	    SAFE_RELEASE(pDuplicator);
    }
    CheckAddFilter(hr, mpDuplicator, TEXT("TCVideoDuplicator"));
#endif

	hr = mpGraph->RenderFile(FileName,NULL);

	if( FAILED(hr) )
	{
		//printf("%s : Render File Error\n", __FUNCTION__);	
		return -1;
	}

    SetLCDController(0, mPrimaryRendererLCDC, mPrimaryRendererImage);

#ifdef __MULTIDISPLAY__
    SetLCDController(1, mSecondlyRendererLCDC, mSecondlyRendererImage);

    pDuplicator=NULL;
    if( SUCCEEDED(mpDuplicator->QueryInterface(IID_ITCVideoDuplicator, (void **)&pDuplicator)) )
    {
        IBaseFilter *pRenderer;
        if( SUCCEEDED(pDuplicator->QueryConnectedDownstreamFilter(1, &pRenderer)) )
        {
            ITccVren *pTCCVRen;
            if( SUCCEEDED(pRenderer->QueryInterface(IID_ITccVren, (void **)&pTCCVRen)) )
            {
                VrenderModeFlag VMF;
					if (m_nType != -1)
					{
						VMF.left=m_stVRM[m_nType+1].left;
						VMF.top=m_stVRM[m_nType+1].top;
						VMF.width=m_stVRM[m_nType+1].right - m_stVRM[m_nType+1].left;
						VMF.height=m_stVRM[m_nType+1].bottom - m_stVRM[m_nType+1].top;
					}
					else
					{
						VMF.left=600;
						VMF.top=360;
						VMF.width=200;
						VMF.height=120;
					}                 

                pTCCVRen->SetModeFlag(VMF);

		        SAFE_RELEASE(pTCCVRen);
            }

            IVideoDestination3 *pVideoDestination;
            if( SUCCEEDED(pRenderer->QueryInterface(IID_IVideoDestination3, (void **)&pVideoDestination)) )
            {
                pVideoDestination->SetEnable(mbSeconldyRenderer?TRUE:FALSE);
                pVideoDestination->Release();
		        SAFE_RELEASE(pVideoDestination);
            }

		    SAFE_RELEASE(pRenderer);
        }
    }
#endif

#if 1
	if( SUCCEEDED(hr) )
	{
		TCHAR mFileNameCation[E_DIVX_CAPTION_MAX][MAX_PATH];
		WIN32_FIND_DATA wfd;
		
		for(iFileType=0; iFileType<E_DIVX_CAPTION_MAX; iFileType++)
		{
			lstrcpy(mFileNameCation[iFileType],FileName);
			pDest = wcsrchr(mFileNameCation[iFileType],'.');
			iResult = pDest-mFileNameCation[iFileType]+1;
			lstrcpy(&mFileNameCation[iFileType][iResult], &CaptionExtension[iFileType][0]);

			if(INVALID_HANDLE_VALUE!=FindFirstFile(mFileNameCation[iFileType],&wfd) )
				break;
		}

		if(iFileType < E_DIVX_CAPTION_MAX)
		{
			//wprintf(_T("mFileNameCation : %s\r\n"), mFileNameCation[iFileType]);

			CheckCoCreateInstance(hr, CLSID_AsyncReader, IID_IBaseFilter, (void **)&mpAsyncReader, TEXT("CLSID_AsyncReader fail"));
			CheckCoCreateInstance(hr, CLSID_TCCCAPTIONPARSER, IID_IBaseFilter, (void **)&mpCaptionParser, TEXT("CLSID_TCCCAPTIONPARSER fail"));
			CheckCoCreateInstance(hr, CLSID_TCCCAPTIONRENDERER, IID_IBaseFilter, (void **)&mpCaptionRenderer, TEXT("CLSID_TCCCAPTIONRENDERER fail"));

			CheckAddFilter(hr, mpCaptionParser, TEXT("TCC Caption Parser"));
			CheckAddFilter(hr, mpCaptionRenderer, TEXT("TCC Caption Renderer"));

			if(SUCCEEDED(hr) && mpCaptionParser)
			{
				ITccCaptionParser* pICaptionParser = NULL;
				hr = mpCaptionParser->QueryInterface(IID_ITccCaptionParser, (void**)&pICaptionParser);
				if( SUCCEEDED(hr) && pICaptionParser)
				{
					pICaptionParser->SetType(iFileType);

					double duration;
					if(GetPlayDuration(&duration) == TRUE)
					{
						pICaptionParser->SetDuration(duration);
					}

					SAFE_RELEASE(pICaptionParser);

					m_CheckDisplayExtCaption = TRUE;
				}
			}

			if(SUCCEEDED(hr))
				hr = mpGraph->RenderFile(mFileNameCation[iFileType],NULL);
		}

#if 1 //for Inner Subtitle
		m_InnerSubTrackNum = 0;
		hr = mpGraph->FindFilterByName(L"TCC CDK Demux Filter", &mpCDKDemux_forInnerSub);
		if(mpCDKDemux_forInnerSub)
		{
			ITCCInnerSubtitleSelect* pInnerSubSelect = NULL;
			hr = mpCDKDemux_forInnerSub->QueryInterface(IID_ITCCInnerSubtitleSelect, (void**)&pInnerSubSelect);
			if(hr==S_OK && pInnerSubSelect)
			{
				pInnerSubSelect->GetSubtitleSubStreamNumber(&m_InnerSubTrackNum);
				pInnerSubSelect->GetSubtitleCurrentSubStream(&m_InnerSubStreamId);
	
				SAFE_RELEASE(pInnerSubSelect);
				//printf("[%s]InnerSubtitle Whole Num : %d\n", __FUNCTION__, m_InnerSubTrackNum);

				if(m_InnerSubTrackNum>0)
				{
					m_CheckDisplayIntCaption = TRUE;
				}
			}
		}
#endif


#ifdef TCCAUDIO_SELECT		
		ITCCAudioSelect *pIAudioSelect=NULL;
		IEnumFilters *pEnum=NULL;
		hr=mpGraph->EnumFilters(&pEnum);

		if(pEnum && hr==S_OK)
		{
			IBaseFilter *pFilter=NULL;
			ULONG c;
			while( S_OK==pEnum->Next(1, &pFilter, &c) )
			{
				if(pFilter)
				{		
					hr=pFilter->QueryInterface(IID_ITCCAudioSelect  , (void**)&pIAudioSelect);
					if(hr==S_OK && pIAudioSelect )
					{
						m_pAVIDemuxer = pFilter;
						pIAudioSelect->GetAudioStreamNum(&m_AudioTrackNum);
						pIAudioSelect->GetAudioCurrentStream(&m_AudioStreamId);

						SAFE_RELEASE(pIAudioSelect);
						break;
					}

					SAFE_RELEASE(pFilter);
			}
		}
		SAFE_RELEASE(pFilter);
		SAFE_RELEASE(pEnum);
		}
#endif		
	}
#endif	

	int rt = SetVRendSize(OutputSize);

#ifdef __EC_COMPLETE_INCLUDE__
	SAFE_RELEASE(m_pMex);
	if(SUCCEEDED(hr=mpGraph->QueryInterface(IID_IMediaEventEx, (void**)&m_pMex)))
	{
		m_pMex->SetNotifyWindow((OAHWND)hWnd, WM_GRAPH_NOTIFY, NULL);		
	}
#endif

	return rt;
}

void CFilterControl::DeleteFiltersForPlaying(void)
{
   if (!mpGraph)
      return;

#ifdef __EC_COMPLETE_INCLUDE__	
	if(m_pMex)
	{
		// Release Event Window
		m_pMex->SetNotifyWindow((OAHWND)NULL, WM_GRAPH_NOTIFY, NULL);		
	}
#endif

#ifdef __MULTIDISPLAY__
   SAFE_RELEASE(mpDuplicator);
#endif

   SAFE_RELEASE(mpCaptionParser);
   SAFE_RELEASE(mpCaptionRenderer);
   SAFE_RELEASE(mpCDKDemux_forInnerSub);
   m_InnerSubTrackNum = 0;
   m_InnerSubStreamId = 0;
   m_CheckDisplayIntCaption = FALSE;
   m_CheckDisplayExtCaption = FALSE;


#ifdef TCCAUDIO_SELECT 
   SAFE_RELEASE(m_pAVIDemuxer);
#endif   
   
   mpGraph->FindFilterByName(L"TCC Video Renderer", &mpVideoRenderer);
   mpGraph->RemoveFilter(mpVideoRenderer);
   SAFE_RELEASE(mpVideoRenderer); // Video Render Filter delete

   // -- Delete other filters
   HRESULT        hr = E_FAIL;
   FILTER_INFO    fiInfo;
   IEnumFilters*  pFilterEnum = NULL;
   int nFilterCount= 0;
   int nPos		= 0;  

   hr = mpGraph->EnumFilters(&pFilterEnum);
	if (FAILED(hr))
      return;

   while (S_OK == pFilterEnum->Skip(1)) {
      nFilterCount++;
   }
   
   IBaseFilter **ppFilters = reinterpret_cast<IBaseFilter **> (_alloca(sizeof(IBaseFilter*)*nFilterCount ) );
   pFilterEnum->Reset();
   
   while (S_OK == pFilterEnum->Next(1, &(ppFilters[nPos++]), NULL))
   {
	   NULL;
   }
   SAFE_RELEASE(pFilterEnum);
   
   for (nPos = 0; nPos < nFilterCount; nPos++)
   {
//#ifdef __DBG_INCLUDE__
      ppFilters[nPos]->QueryFilterInfo(&fiInfo);
      char name[80];
      WideCharToMultiByte(CP_ACP, 0, fiInfo.achName, -1, name, 80, NULL, NULL);
      printf("DeleteFilters() - %s\r\n", name);   
      ULONG r1=ppFilters[nPos]->AddRef();
      ULONG r2=ppFilters[nPos]->Release();

      fiInfo.pGraph->Release();
 //#endif        
      mpGraph->RemoveFilter(ppFilters[nPos]);
      SAFE_RELEASE(ppFilters[nPos]);
   }

#ifdef __MULTIDISPLAY__
    if( mpDuplicator )
        mpGraph->RemoveFilter(mpDuplicator);
    SAFE_RELEASE(mpDuplicator);
#endif

	if(mpAsyncReader)
		mpGraph->RemoveFilter(mpAsyncReader);
	if(mpCaptionParser)
		mpGraph->RemoveFilter(mpCaptionParser);
	if(mpCaptionRenderer)
		mpGraph->RemoveFilter(mpCaptionRenderer);
	
	SAFE_RELEASE(mpAsyncReader);
	SAFE_RELEASE(mpCaptionParser);
	SAFE_RELEASE(mpCaptionRenderer);
}

BOOL CFilterControl::GetPlayDuration(double *duration)
{
	if (!mpGraph)
		return FALSE;
	
	IMediaControl* p_mc = NULL;
	HRESULT hr = mpGraph->QueryInterface(IID_IMediaControl, (void **)&p_mc);
	if( hr==S_OK )
	{
		IMediaPosition *pMediaPosition;

		p_mc->QueryInterface(IID_IMediaPosition,(void**)&pMediaPosition);

		pMediaPosition->get_Duration(duration);		

		SAFE_RELEASE(pMediaPosition);
	}

	SAFE_RELEASE(p_mc);
	return SUCCEEDED(hr);
}

BOOL CFilterControl::GetCurrentPlayTime(double *pos)
{
	if (!mpGraph)
		return FALSE;
	
	IMediaControl* p_mc = NULL;
	HRESULT hr = mpGraph->QueryInterface(IID_IMediaControl, (void **)&p_mc);
	if( hr==S_OK )
	{
		IMediaPosition *pMediaPosition;

		p_mc->QueryInterface(IID_IMediaPosition,(void**)&pMediaPosition);
		
		pMediaPosition->get_CurrentPosition(pos);

		SAFE_RELEASE(pMediaPosition);
	}

	SAFE_RELEASE(p_mc);
	return SUCCEEDED(hr);
}

BOOL CFilterControl::SetCurrentPlayTime(double pos)
{
	if (!mpGraph)
		return FALSE;

	IMediaControl* p_mc = NULL;
	HRESULT hr = mpGraph->QueryInterface(IID_IMediaControl, (void **)&p_mc);
	if( hr==S_OK )
	{
#if 1	
		IMediaSeeking *pMediaSeeking;
		
		p_mc->QueryInterface(IID_IMediaSeeking,(void**)&pMediaSeeking);

		LONGLONG StartTime = pos * 1000 * 10000;
		pMediaSeeking->SetPositions(&StartTime, AM_SEEKING_SeekToKeyFrame | AM_SEEKING_AbsolutePositioning | AM_SEEKING_ReturnTime, NULL, AM_SEEKING_NoPositioning);

		SAFE_RELEASE(pMediaSeeking);

		if(SUCCEEDED(hr) && mpCaptionParser)
		{
			ITccCaptionParser* pICaptionParser = NULL;
			hr = mpCaptionParser->QueryInterface(IID_ITccCaptionParser, (void**)&pICaptionParser);
			if( SUCCEEDED(hr) && pICaptionParser)
			{
				pICaptionParser->SetStartTime(StartTime);	

				SAFE_RELEASE(pICaptionParser);
			}
		}
#endif
	}

	SAFE_RELEASE(p_mc);
	return SUCCEEDED(hr);
}

BOOL CFilterControl::CheckAddFilter(HRESULT &hr, IBaseFilter *pBaseFilter, LPCTSTR pszFilterName)
{
	if( SUCCEEDED(hr) )
	{
		hr=mpGraph->AddFilter(pBaseFilter, pszFilterName);
		if( SUCCEEDED(hr) )
		{
			return TRUE;
		}
		else
		{
			TCHAR tmp[256];
			::wsprintf(tmp, TEXT("[FAIL]AddFilter %s"), pszFilterName);
			
			///::MessageBox(NULL, tmp, TEXT("DVBTFilterGraph"), 0);
			::printf("[FAIL]AddFilter %ls\n", pszFilterName);
		}
	}

	return FALSE;
}

int CFilterControl::GetVIQEmodes(VIQEModeFlag	&flag)
{
#ifdef __VIQE__
#ifdef __DBG_INCLUDE__
	printf("[CFilterControl::GetVIQEmodes]\n");
#endif

	HRESULT hr=S_OK;

	if(mpGraph)
	{		
		hr = mpGraph->FindFilterByName(L"TCC Video Renderer", &mpVideoRenderer);
		if(!SUCCEEDED(hr))
		{
			hr = mpGraph->FindFilterByName(L"TCVideoRenderer", &mpVideoRenderer);
		}
#ifdef __DBG_INCLUDE__
		printf("[CFilterControl::GetVIQEmodes]mpGraph->FindFilterByName\n");
#endif
		{
			if (mpVideoRenderer)
			{				
				ITccVren5* pIVren = NULL;
								
				memset(&flag,0,sizeof(VIQEModeFlag));

				hr = mpVideoRenderer->QueryInterface(IID_ITccVren5, (void**)&pIVren);
				printf("[CFilterControl::GetVIQEmodes]mpVideoRenderer->QueryInterface\n");
				if( SUCCEEDED(hr) && pIVren)
				{							
					pIVren->GetVIQEModeFlag(&flag);		

					SAFE_RELEASE(pIVren);
					SAFE_RELEASE(mpVideoRenderer);
					return 1;
				}
			}
			else
			{
				printf("[%s]Fail to find Video Render\n", __FUNCTION__);
			}		
		}
	}
#endif
	return 0;	
}
int CFilterControl::SetVIQEmodes(VIQEModeFlag	flag)
{
#ifdef __VIQE__
#ifdef __DBG_INCLUDE__
	printf("[CFilterControl::SetVIQEmodes]\n");
#endif

	HRESULT hr=S_OK;

	if(mpGraph)
	{		
		hr = mpGraph->FindFilterByName(L"TCC Video Renderer", &mpVideoRenderer);
		if(!SUCCEEDED(hr))
		{
			hr = mpGraph->FindFilterByName(L"TCVideoRenderer", &mpVideoRenderer);
		}
#ifdef __DBG_INCLUDE__
		printf("[CFilterControl::SetVIQEmodes]mpGraph->FindFilterByName\n");
#endif
		{
			if (mpVideoRenderer)
			{				
				ITccVren5* pIVren = NULL;
				VIQEModeFlag	VIQEflag;
				memset(&VIQEflag,0,sizeof(VIQEflag));

				// mode = 1, chroma key @ RGB(16,0,16)
				VIQEflag = flag;		
				
				hr = mpVideoRenderer->QueryInterface(IID_ITccVren5, (void**)&pIVren);
				//printf("[CFilterControl::SetVIQEmodes]mpVideoRenderer->QueryInterface\n");
				if( SUCCEEDED(hr) && pIVren)
				{				
#ifdef __DBG_INCLUDE__					
#endif
					pIVren->SetVIQEModeFlag(VIQEflag);					

					SAFE_RELEASE(pIVren);
					SAFE_RELEASE(mpVideoRenderer);
					return 1;
				}
			}
			else
			{
				printf("Fail SetVIQEmodes\n");
			}		
		}
	}
#endif
	return 0;	
}


#ifdef __FILTER_SPEED_CONTROL__
double	CFilterControl::dSpeedSet(int nIndex, int nType)
{
	if (nType == 1)
	{
		switch(nIndex)
		{
		case 6:		m_nIndex = 5;	 return 4.0;		break;	
		case 5:		return 4.0;		break;
		case 4:		return 2.0;		break;
		case 3:		return 1.8;		break;
		case 2:		return 1.4;		break;
		case 1:		return 1.2;		break;
		case 0:		return 1.0;		break;	
		case -1:	return 0.8;		break;	
		case -2:	return 0.6;		break;	
		case -3:	return 0.2;		break;	
		case -4:	m_nIndex = -3;		return 0.2;		break;	
		}
	}
	else if (nType == 0)
	{
		switch(nIndex)
		{
		case 4:		m_nIndex = 3;	 return 8.0;		break;	
		case 3:		return 8.0;		break;
		case 2:		return 4.0;		break;
		case 1:		return 2.0;		break;		
		case 0:		return 1.0;		break;	
		case -1:	return 0.8;		break;	
		case -2:	return 0.6;		break;	
		case -3:	return 0.2;		break;	
		case -4:	m_nIndex = -3;		return 0.2;		break;	
		}
	}
	else
	{
		printf("[%s] Input nType is Error\n");
		return 0.0;
	}
	
	
}
void CFilterControl::FilterSpeedDown(int nType)
{
	HRESULT hr=S_OK;	
	hr = m_pMediaSeeking->SetRate(dSpeedSet(--m_nIndex, nType));	
}
void CFilterControl::FilterSpeedUp(int nType)
{
	HRESULT hr=S_OK;	
	hr = m_pMediaSeeking->SetRate(dSpeedSet(++m_nIndex, nType));
}
void CFilterControl::FilterSpeedNormal()
{
	HRESULT hr=S_OK;	
	m_nIndex = 0;
	hr = m_pMediaSeeking->SetRate(dSpeedSet(0, 1));
}

double CFilterControl::GetCurrentSpeed(int nType)
{
	return dSpeedSet(m_nIndex, nType);
}
#endif

int CFilterControl::SetVRendSize(CRect NewOutputSize)
{
#ifdef __DBG_INCLUDE__
	printf("[CFilterControl::SetVRendSize]\n");
#endif

	HRESULT hr=S_OK;

	if(mpGraph)
	{		
		hr = mpGraph->FindFilterByName(L"TCC Video Renderer", &mpVideoRenderer);
		if(!SUCCEEDED(hr))
		{
			hr = mpGraph->FindFilterByName(L"TCVideoRenderer", &mpVideoRenderer);
		}
#ifdef __DBG_INCLUDE__
		printf("[CFilterControl::SetVRendSize]mpGraph->FindFilterByName\n");
#endif
		{
			if (mpVideoRenderer)
			{				
				ITccVren* pIVren = NULL;

				memset(&Rendererflag,0,sizeof(VrenderModeFlag));

				// mode = 1, chroma key @ RGB(16,0,16)
				Rendererflag.mode	=	1;
				Rendererflag.left	=	NewOutputSize.left;
				Rendererflag.top	=	NewOutputSize.top;
				Rendererflag.width	=	NewOutputSize.right - NewOutputSize.left;
				Rendererflag.height	=	NewOutputSize.bottom - NewOutputSize.top;
//				Rendererflag.Chromakey = CHROMAKEY_COLOR;
				
				hr = mpVideoRenderer->QueryInterface(IID_ITccVren, (void**)&pIVren);
				//printf("[CFilterControl::SetVRendSize]mpVideoRenderer->QueryInterface\n");
				if( SUCCEEDED(hr) && pIVren)
				{				
#ifdef __DBG_INCLUDE__
					printf("[CFilterControl::CreateFilterForPlaying] Set VRender\n");
					printf("   - Mode   : %d\n",Rendererflag.mode);
					printf("   - left   : %d\n",Rendererflag.left);
					printf("   - top    : %d\n",Rendererflag.top);
					printf("   - width  : %d\n",Rendererflag.width);
					printf("   - height : %d\n",Rendererflag.height);
					//printf("   - Chromakey : 0x%x\n",Rendererflag.Chromakey);
#endif
					pIVren->SetModeFlag(Rendererflag);					
					SAFE_RELEASE(pIVren);
					SAFE_RELEASE(mpVideoRenderer);
					return 1;
				}
			}
			else
			{
				printf("[%s]Fail to find Video Render\n", __FUNCTION__);
				return -2;
			}		
		}
	}
	
	return 0;	
}
#ifdef __ROTATE_INCLUDE__
int CFilterControl::RotateVRend(CRect NewOutputSize, int Mode)
{
	HRESULT hr=S_OK;

	if(mpGraph)
	{		
		mpGraph->FindFilterByName(L"TCC Video Renderer", &mpVideoRenderer);

		{
			if (mpVideoRenderer)
			{				
				ITccVren5* pIVren = NULL;

				memset(&Rendererflag,0,sizeof(VrenderModeFlag));

				// mode = 1, chroma key @ RGB(16,0,16)
				Rendererflag.mode	=	1;
				Rendererflag.left	=	NewOutputSize.left;
				Rendererflag.top	=	NewOutputSize.top;
				Rendererflag.width	=	NewOutputSize.right - NewOutputSize.left;
				Rendererflag.height	=	NewOutputSize.bottom - NewOutputSize.top;

				Rendererflag.Rotate = Mode;
				if(Rendererflag.Rotate == 1 || Rendererflag.Rotate == 3)
				{
					Rendererflag.width = NewOutputSize.bottom - NewOutputSize.top;
					Rendererflag.height = NewOutputSize.right - NewOutputSize.left;
				}

//				Rendererflag.Chromakey = CHROMAKEY_COLOR;
				
				hr = mpVideoRenderer->QueryInterface(IID_ITccVren, (void**)&pIVren);
				printf("[CFilterControl::SetVRendSize]mpVideoRenderer->QueryInterface\n");
				if( SUCCEEDED(hr) && pIVren)
				{				
//#ifdef __DBG_INCLUDE__
					printf("[CFilterControl::CreateFilterForPlaying] Set VRender\n");
					printf("   - Mode   : %d\n",Rendererflag.mode);
					printf("   - left   : %d\n",Rendererflag.left);
					printf("   - top    : %d\n",Rendererflag.top);
					printf("   - width  : %d\n",Rendererflag.width);
					printf("   - height : %d\n",Rendererflag.height);
					printf("   - Rotate : %d\n",Rendererflag.Rotate);
					//printf("   - Chromakey : 0x%x\n",Rendererflag.Chromakey);
//#endif
					pIVren->ResizeCurrentFrame(Rendererflag);					

					SAFE_RELEASE(pIVren);
					SAFE_RELEASE(mpVideoRenderer);
					return 1;
				}
			}
			else
			{
				printf("[%s]Fail to find Video Render\n", __FUNCTION__);
			}		
		}
	}
	
	return 0;	
}
#endif

int CFilterControl::SetCaptionLanguage(int index)
{
	HRESULT hr=S_OK;

	if(SUCCEEDED(hr) && mpCaptionParser)
	{
		ITccCaptionParser* pICaptionParser = NULL;
		hr = mpCaptionParser->QueryInterface(IID_ITccCaptionParser, (void**)&pICaptionParser);
		if( SUCCEEDED(hr) && pICaptionParser)
		{
			pICaptionParser->SetLanguage(index);

			SAFE_RELEASE(pICaptionParser);
		}
	}

	return 0;
}

int CFilterControl::SetCaptionHWND(HWND hWnd)
{
	HRESULT hr=S_OK;

	ITCCSubtitleRenderer *pTCCSubtitleRenderer=NULL;
	IEnumFilters *pEnum=NULL;
	IBaseFilter *pFilter=NULL;
	hr=mpGraph->EnumFilters(&pEnum);

	if(pEnum && hr==S_OK)
	{		
		ULONG c;
		while( S_OK==pEnum->Next(1, &pFilter, &c) )
		{
			if(pFilter)
			{		
				hr=pFilter->QueryInterface(IID_ITCCSubtitleRenderer  , (void**)&pTCCSubtitleRenderer);
				if(hr==S_OK && pTCCSubtitleRenderer )
				{
					pTCCSubtitleRenderer->SetWindow(hWnd);

					SAFE_RELEASE(pTCCSubtitleRenderer);
				}

				SAFE_RELEASE(pFilter);
			}
		}
		SAFE_RELEASE(pFilter);
		SAFE_RELEASE(pEnum);
	}

	return 0;
}

int CFilterControl::SetCaptionInfo(CaptionRenderInfo CaptionInfo)
{
	HRESULT hr=S_OK;

	ITCCSubtitleRenderer *pTCCSubtitleRenderer=NULL;
	IEnumFilters *pEnum=NULL;
	IBaseFilter *pFilter=NULL;
	hr=mpGraph->EnumFilters(&pEnum);

	if(pEnum && hr==S_OK)
	{		
		ULONG c;
		while( S_OK==pEnum->Next(1, &pFilter, &c) )
		{
			if(pFilter)
			{		
				hr=pFilter->QueryInterface(IID_ITCCSubtitleRenderer  , (void**)&pTCCSubtitleRenderer);
				if(hr==S_OK && pTCCSubtitleRenderer )
				{
					LOGFONT lf;
					lf.lfHeight=CaptionInfo.fontsize;
					lf.lfWidth=0;
					lf.lfEscapement=0;
					lf.lfOrientation=0;
					lf.lfWeight=FW_NORMAL;
					lf.lfItalic=0;
					lf.lfUnderline=0;
					lf.lfStrikeOut=0;
					lf.lfCharSet=DEFAULT_CHARSET;
					lf.lfOutPrecision=OUT_DEFAULT_PRECIS;
					lf.lfClipPrecision=CLIP_DEFAULT_PRECIS;
					lf.lfQuality=DEFAULT_QUALITY;
					lf.lfPitchAndFamily=DEFAULT_PITCH;
					::lstrcpy(lf.lfFaceName, TEXT("arial"));

					RECT rt={CaptionInfo.left, CaptionInfo.top, CaptionInfo.left+CaptionInfo.width, CaptionInfo.top+CaptionInfo.height};

					pTCCSubtitleRenderer->SetFont(&lf);
					pTCCSubtitleRenderer->SetEnable(CaptionInfo.enable);
					pTCCSubtitleRenderer->SetDestinationRect(&rt);
					pTCCSubtitleRenderer->SetBottomMargin(10);

					SAFE_RELEASE(pTCCSubtitleRenderer);
				}

				SAFE_RELEASE(pFilter);
			}
		}
		SAFE_RELEASE(pFilter);
		SAFE_RELEASE(pEnum);
	}
	return 0;
}

void CFilterControl::ReRenderSubtitle(void)
{
	HRESULT hr=S_OK;

	if(mpGraph && mpCaptionRenderer == NULL)
		hr = mpGraph->FindFilterByName(L"TCCSubtitleRenderer", &mpCaptionRenderer);

	if( mpGraph && mpCaptionRenderer )
	{
		ITCCSubtitleRenderer2 *pTCCSubtitleRenderer2=NULL;
		hr=mpCaptionRenderer->QueryInterface(IID_ITCCSubtitleRenderer2, (void **)&pTCCSubtitleRenderer2);
		if( SUCCEEDED(hr) && pTCCSubtitleRenderer2 )
		{
			pTCCSubtitleRenderer2->ReRender();

			SAFE_RELEASE(pTCCSubtitleRenderer2);
		}
	}
}

BOOL CFilterControl::BitBltToHDMI(int x, int y, int w, int h, void *pSource, int SourceWidthBytes, int sx, int sy)
{
	HRESULT hr=E_FAIL;

	if(mpGraph && mpCaptionRenderer == NULL)
		hr = mpGraph->FindFilterByName(L"TCCSubtitleRenderer", &mpCaptionRenderer);

	if( mpGraph && mpCaptionRenderer )
	{
		IExportBitBlt *pExportBitBlt=NULL;
		hr=mpCaptionRenderer->QueryInterface(IID_IExportBitBlt, (void **)&pExportBitBlt);
		if( SUCCEEDED(hr) && pExportBitBlt )
		{
			hr=pExportBitBlt->BitBltToFrameBuffer(x, y, w, h, pSource, SourceWidthBytes, sx, sy);

			SAFE_RELEASE(pExportBitBlt);
		}
	}

    return SUCCEEDED(hr);
}

BOOL CFilterControl::CaptureCurrentSampleBufferYuv420(BYTE *pBuffer, int *pWidth, int *pHeight, int *pBufferSize, DWORD dwMilliseconds,BOOL *bInterleaved)
{
	HRESULT hr=mpGraph->FindFilterByName(L"TCC Video Renderer", &mpVideoRenderer);
	if( FAILED(hr) )
	{
		hr=mpGraph->FindFilterByName(L"TCVideoRenderer", &mpVideoRenderer);
	}

    if( SUCCEEDED(hr) )
    {
	    ITCCVideoSampleGrabber *pTCCVideoSampleGrabber=NULL;
        hr=mpVideoRenderer->QueryInterface(IID_ITCCVideoSampleGrabber, (void **)&pTCCVideoSampleGrabber);
        if( SUCCEEDED(hr) )
        {
            hr=pTCCVideoSampleGrabber->GetSample(pBuffer, pWidth, pHeight, pBufferSize, dwMilliseconds, NULL, bInterleaved, NULL);
            SAFE_RELEASE(pTCCVideoSampleGrabber);
        }

	    if( FAILED(hr) )
        {		
		    ITccVren3 *pIVren=NULL;

		    HRESULT hr=mpVideoRenderer->QueryInterface(IID_ITccVren3, (void**)&pIVren);
		    if( SUCCEEDED(hr) && pIVren )
		    {
			    hr=pIVren->CaptureSampleBufferYuv420(pBuffer, pWidth, pHeight, pBufferSize, dwMilliseconds);
			    SAFE_RELEASE(pIVren);
		    }

		    *bInterleaved = 1;

		    SAFE_RELEASE(mpVideoRenderer);
	     }
    }

	return SUCCEEDED(hr);
}

#ifdef __EC_COMPLETE_INCLUDE__
HRESULT CFilterControl::GetNotifyEvent(long *evCode,LONG *param1,LONG *param2)
{
	if(m_pMex)
	{
		return m_pMex->GetEvent(evCode,param1, param2, 0);
	}
	else
		return E_FAIL;
}

HRESULT CFilterControl::FreeEventParams(long evCode,LONG param1,LONG param2)
{
	if(m_pMex)
	{
		return m_pMex->FreeEventParams(evCode, param1, param2);
	}
	else
		return E_FAIL;
}
#endif

HRESULT CFilterControl::SetLCDController(int Renderer, int LCDC, int Image)
{
    HRESULT hr=E_FAIL;

#ifdef __MULTIDISPLAY__
    ITCVideoDuplicator *pDuplicator;
    hr=mpDuplicator->QueryInterface(IID_ITCVideoDuplicator, (void **)&pDuplicator);
    if( SUCCEEDED(hr) )
    {
        IBaseFilter *pRenderer;
        hr=pDuplicator->QueryConnectedDownstreamFilter(Renderer, &pRenderer);
        if( SUCCEEDED(hr) )
        {
            IVideoDestination3 *pVideoDestination;
            hr=pRenderer->QueryInterface(IID_IVideoDestination3, (void **)&pVideoDestination);
            if( SUCCEEDED(hr) )
            {
                hr=pVideoDestination->SetLCDController(LCDC, Image);
                SAFE_RELEASE(pVideoDestination);
            }

	    SAFE_RELEASE(pRenderer);
        }
    }

#else

    if( 0==Renderer )
    {
        IBaseFilter *pVideoRenderer;
        hr=mpGraph->FindFilterByName(L"TCVideoRenderer", &pVideoRenderer);
        if( SUCCEEDED(hr) )
        {
            IVideoDestination3 *pVideoDestination;
            hr=pVideoRenderer->QueryInterface(IID_IVideoDestination3, (void **)&pVideoDestination);
            if( SUCCEEDED(hr) )
            {
                hr=pVideoDestination->SetLCDController(mPrimaryRendererLCDC, mPrimaryRendererImage);
		        SAFE_RELEASE(pVideoDestination);
            }

		    SAFE_RELEASE(pVideoRenderer);
        }
    }
#endif

    return hr;
}

#ifdef VPU_CLOCK_CONTROL
BOOL CFilterControl::SetVPUClockControl(int VBUS, int VCODEC)
{
	HRESULT hr=S_OK;

	printf("========[MovieManager - SetVPUClockControl]========\n");
	printf("== VBUS : %d, VCODEC : %d\n", VBUS, VCODEC);
	printf("===================================================\n");

	if(mpGraph)
	{
		mpGraph->FindFilterByName(L"TCC VPUDec Filter", &mVpuDec);

		if (mVpuDec)
		{
			ITccVpuControl *pIVPUDec = NULL;
			hr = mVpuDec->QueryInterface(IID_ITccVpuControl, (void**)&pIVPUDec);
	
			if( SUCCEEDED(hr) && pIVPUDec )
			{		
				hr = pIVPUDec->SetVPUClockControl(VBUS,VCODEC);
				if( FAILED(hr) )
				{
					TCHAR tmp[256];
					::wsprintf(tmp, TEXT("SetVPUClockControl(%d,%d)"),VBUS,VCODEC);
					::MessageBox(NULL, tmp, TEXT("TCCMovieManager"), MB_ICONWARNING);
				}
			}
			SAFE_RELEASE(pIVPUDec);
		}
		SAFE_RELEASE(mVpuDec);
	}

	return SUCCEEDED(hr);
}
#endif

#ifdef __RESIZE__
void	CFilterControl::CurrentFrameResize(CRect vrect)
{
	HRESULT hr=S_OK;

	if(mpGraph)
	{		
		mpGraph->FindFilterByName(L"TCC Video Renderer", &mpVideoRenderer);
		{
			if (mpVideoRenderer)
			{				
				ITccVren5* pIVren = NULL;

				VrenderModeFlag flag;
				memset(&flag, 0, sizeof(VrenderModeFlag));

				flag.mode	=	1;
				flag.left	=	vrect.left;
				flag.top	=	vrect.top;
				flag.width	=	vrect.right - vrect.left;
				flag.height	=	vrect.bottom - vrect.top;

				hr = mpVideoRenderer->QueryInterface(IID_ITccVren5, (void**)&pIVren);
				//printf("[%s]mpVideoRenderer->QueryInterface\n", __FUNCTION__);
				if( SUCCEEDED(hr) && pIVren)
				{						
					pIVren->ResizeCurrentFrame(flag);
					
					SAFE_RELEASE(pIVren);
					SAFE_RELEASE(mpVideoRenderer);
					return;
				}
			}
			else
			{
				printf("[%s]Fail to find Video Render\n", __FUNCTION__);
			}		
		}
	}
}
#endif

BOOL	CFilterControl::GettVRender(tVRender &pVflag, DWORD dwMilliseconds)
{
	HRESULT hr=S_OK;
	
	if(mpGraph)
	{		
		mpGraph->FindFilterByName(L"TCC Video Renderer", &mpVideoRenderer);
		{
			if (mpVideoRenderer)
			{				
				ITccVren6* pIVren = NULL;

				memset(&pVflag,0,sizeof(pVflag));

				hr = mpVideoRenderer->QueryInterface(IID_ITccVren6, (void**)&pIVren);
				printf("[CFilterControl::GettVRender]mpVideoRenderer->QueryInterface\n");
				if( SUCCEEDED(hr) && pIVren)
				{						
					bool bResult = (pIVren->GettVRender(&pVflag, dwMilliseconds) == S_OK);				
					SAFE_RELEASE(pIVren);
					SAFE_RELEASE(mpVideoRenderer);
					if (bResult)
					{
						return TRUE;
					}
					else
					{
						MessageBox(NULL, _T("GettVRender is failed!"), NULL, 1);
						return FALSE;
					}					
				}				
			}
			else
			{
				printf("[%s]Fail to find Video Render\n", __FUNCTION__);
			}		
		}
	}
	return FALSE;
}
#ifdef __EDIT_CHROMAKEY_VALUE__
void	CFilterControl::SetRendererChromakeyValue(int nRValue, int nGValue, int BValue)
{
	HRESULT hr = S_OK;
	if (mpGraph)
	{
		mpGraph->FindFilterByName(L"TCC Video Renderer", &mpVideoRenderer);
		{
			if (mpVideoRenderer)
			{				
				ITccChromakey* pIVren = NULL;

				hr = mpVideoRenderer->QueryInterface(IID_ITccChromakey, (void**)&pIVren);
				
				if( SUCCEEDED(hr) && pIVren)
				{						
					pIVren->SetChromakeyValue(nRValue, nGValue, nRValue);		
					SAFE_RELEASE(pIVren);
				}				
				SAFE_RELEASE(mpVideoRenderer);
			}
			else
			{
				printf("[%s]Fail to find Video Render\n", __FUNCTION__);
			}		
		}
	}
}

#endif

#ifdef TCCAUDIO_SELECT
BOOL CFilterControl::SelectAudioNum()
{
	ITCCAudioSelect *pIAudioSelect=NULL;
	LONGLONG llPos;
	if (m_pMediaSeeking)
	{
		m_pMediaSeeking->GetCurrentPosition(&llPos);		
	}
	else
	{
		return FALSE;
	}
	if (m_pAVIDemuxer)
	{
		m_pAVIDemuxer->QueryInterface(IID_ITCCAudioSelect  , (void**)&pIAudioSelect);
		pIAudioSelect->SetAudioStream(m_AudioStreamId);
		printf("[%s] m_AudioStreamId = %d\n", __FUNCTION__, m_AudioStreamId);
		SAFE_RELEASE(pIAudioSelect);
	}
	else
	{
		return FALSE;
	}
	if (m_pMediaSeeking)
	{		
		m_pMediaSeeking->SetPositions(&llPos
			,AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame
			,0,AM_SEEKING_NoPositioning);			
	}
	else
	{
		return FALSE;
	}
	return TRUE;
}
#endif

BOOL CFilterControl::SelectInnerSubNum()
{
	
	ITCCInnerSubtitleSelect* pInnerSubSelect = NULL;

#if 0
	LONGLONG llPos;
	if (m_pMediaSeeking)
	{
		m_pMediaSeeking->GetCurrentPosition(&llPos);		
	}
	else
	{
		return FALSE;
	}
#endif

	if (mpCDKDemux_forInnerSub)
	{
		mpCDKDemux_forInnerSub->QueryInterface(IID_ITCCInnerSubtitleSelect  , (void**)&pInnerSubSelect);
		pInnerSubSelect->SetSubtitleSubStream(m_InnerSubStreamId);
		printf("[%s] m_InnerSubStreamId = %d\n", __FUNCTION__, m_InnerSubStreamId);
		SAFE_RELEASE(pInnerSubSelect);
	}
	else
	{
		return FALSE;
	}

#if 0
	if (m_pMediaSeeking)
	{		
		m_pMediaSeeking->SetPositions(&llPos
			,AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame
			,0,AM_SEEKING_NoPositioning);			
	}
	else
	{
		return FALSE;
	}
#endif

	return TRUE;
}

BOOL CFilterControl::SetAudioVolume(unsigned int AudioVolume)
{
	if (AudioVolume > MAX_VOLUMES)
		AudioVolume = MAX_VOLUMES;
	
	LONG volume = s_volume_values[AudioVolume];

	if (!mpGraph)
		return FALSE;

	IBasicAudio* p_basic_audio = NULL;
	HRESULT hr = mpGraph->QueryInterface(IID_IBasicAudio, (void**)&p_basic_audio);
	if(SUCCEEDED(hr))
	{
		p_basic_audio->put_Volume(volume);
	}
	SAFE_RELEASE(p_basic_audio);	
	return SUCCEEDED(hr);
}

BOOL CFilterControl::GetAudioVolume(unsigned int* pAudioVolume)
{
	if (!mpGraph)
		return FALSE;
		
	LONG volume = 0;
	
	IBasicAudio* p_basic_audio = NULL;
	HRESULT hr = mpGraph->QueryInterface(IID_IBasicAudio, (void**)&p_basic_audio);
	if(SUCCEEDED(hr))
	{
		p_basic_audio->get_Volume(&volume);
	}
	SAFE_RELEASE(p_basic_audio);

	for(int i=0; i<MAX_VOLUMES; i++)
	{
		if(volume <= s_volume_values[i])
		{
			*pAudioVolume = i;
			break;
		}
	}
	return SUCCEEDED(hr);
}

unsigned int CFilterControl::GetSeekablility()
{
	unsigned int Seekable = 1;

	if(mpGraph)
	{
		ITCCSeekInterface *pSeekInterface;
		IEnumFilters *pEnum=NULL;
		HRESULT hr=mpGraph->EnumFilters(&pEnum);
		if(pEnum && hr==S_OK)
		{
			IBaseFilter *pFilter=NULL;
			ULONG c;
			while( S_OK==pEnum->Next(1, &pFilter, &c) )
			{
				if(pFilter)
				{		
					hr=pFilter->QueryInterface(IID_ITCCSeekInterface  , (void**)&pSeekInterface);
					if(hr==S_OK && pSeekInterface )
					{
						pSeekInterface->GetSeekAbility(&Seekable);
						SAFE_RELEASE(pSeekInterface);						
						break;
					}
					SAFE_RELEASE(pFilter);
				}
			}
			SAFE_RELEASE(pFilter);
			SAFE_RELEASE(pEnum);
		}
	}

	return Seekable;
}

// MediaInfo Replace[11/27/2009 b090136]
int CFilterControl::Get_VideoHeight()
{
	if(mpGraph)
	{
	    IBasicVideo* pIBasicVideo = NULL;
	    long lHeight=0;

		HRESULT hr=mpGraph->QueryInterface(IID_IBasicVideo, (void**)&pIBasicVideo);
        if( SUCCEEDED(hr) )
        {
		    pIBasicVideo->get_VideoHeight(&lHeight);	    
        }

	    SAFE_RELEASE(pIBasicVideo);
        return lHeight;
	}

	return 0xff;	
}

int CFilterControl::Get_VideoWidth()
{
	IBasicVideo* pIBasicVideo = NULL;
	long lWidth;
	HRESULT hr = mpGraph->QueryInterface(IID_IBasicVideo, (void**)&pIBasicVideo);
	pIBasicVideo->get_VideoWidth(&lWidth);
	SAFE_RELEASE(pIBasicVideo);	
	return (int)lWidth;	
}

double CFilterControl::Get_Bitrate()
{
	IBasicVideo* pIBasicVideo = NULL;
	long lBitrate;
	HRESULT hr = mpGraph->QueryInterface(IID_IBasicVideo, (void**)&pIBasicVideo);
	pIBasicVideo->get_BitRate(&lBitrate);
	SAFE_RELEASE(pIBasicVideo);
	return (double)lBitrate;	
}
int CFilterControl::Get_SourceHeight()
{
	IBasicVideo* pIBasicVideo = NULL;
	long lSourceHeight;
	HRESULT hr = mpGraph->QueryInterface(IID_IBasicVideo, (void**)&pIBasicVideo);
	pIBasicVideo->get_SourceHeight(&lSourceHeight);
	SAFE_RELEASE(pIBasicVideo);
	return (int)lSourceHeight;	
}
int CFilterControl::Get_SourceWidth()
{
	IBasicVideo* pIBasicVideo = NULL;	
	long lSourceWidth;
	HRESULT hr = mpGraph->QueryInterface(IID_IBasicVideo, (void**)&pIBasicVideo);
	pIBasicVideo->get_SourceWidth(&lSourceWidth);
	SAFE_RELEASE(pIBasicVideo);	
	return (int)lSourceWidth;	
}

VideoInfo CFilterControl::Get_VideoInfo()
{
	VideoInfo rt;
	rt.FourCC = NULL;
	if (mpGraph)
	{
		ITCCVideoInfo *pIVideoInfo;	
		IEnumFilters *pEnum=NULL;
		HRESULT hr=mpGraph->EnumFilters(&pEnum);
		if(pEnum && hr==S_OK)
		{
			IBaseFilter *pFilter=NULL;
			ULONG c;
			while( S_OK==pEnum->Next(1, &pFilter, &c) )
			{			
				if(pFilter)
				{		
					hr=pFilter->QueryInterface(IID_ITCCVideoInfo  , (void**)&pIVideoInfo);
					if(hr==S_OK && pIVideoInfo )
					{	
						pIVideoInfo->GetVideoInfo(&rt);		
						pIVideoInfo->Release();
						pIVideoInfo = NULL;						
						break;
					}
					SAFE_RELEASE(pFilter);
				}
			}
			SAFE_RELEASE(pFilter);
			SAFE_RELEASE(pEnum);	
			if (rt.FourCC == NULL)// FLVDEMUX [12/17/2009 b090136]
			{
				printf("Not supported by CDK Video\n");
				IEnumFilters *pEnumFLV=NULL;
				HRESULT hr=mpGraph->EnumFilters(&pEnumFLV);
				while( S_OK==pEnumFLV->Next(1, &pFilter, &c) )
				{			
					if(pFilter)
					{		
						hr=pFilter->QueryInterface(IID_ITCCFLVVideoInfo, (void**)&pIVideoInfo);
						if(hr==S_OK && pIVideoInfo )
						{	
							pIVideoInfo->GetVideoInfo(&rt);		
							pIVideoInfo->Release();
							pIVideoInfo = NULL;													
							break;							
						}
						SAFE_RELEASE(pFilter);
					}
				}
				SAFE_RELEASE(pFilter);
				SAFE_RELEASE(pEnumFLV);		
			}					
		}				
	}
	return rt;
}
AudioInfo CFilterControl::Get_AudioInfo()
{
	AudioInfo rt;
	rt.audioCodec = 0;
	rt.bitrate = 0;
	rt.channel = 0;
	rt.samplerate = 0;

	if (mpGraph)
	{
		ITCCAudioInfo *pIAudioInfo;	
		IEnumFilters *pEnum=NULL;
		HRESULT hr=mpGraph->EnumFilters(&pEnum);
		if(pEnum && hr==S_OK)
		{
			IBaseFilter *pFilter=NULL;
			ULONG c;
			while( S_OK==pEnum->Next(1, &pFilter, &c) )
			{			
				if(pFilter)
				{		
					hr=pFilter->QueryInterface(IID_ITCCAudioInfo  , (void**)&pIAudioInfo);
					if(hr==S_OK && pIAudioInfo )
					{	
						pIAudioInfo->GetAudioInfo(&rt);		
						pIAudioInfo->Release();
						pIAudioInfo = NULL;						
						break;
					}
					SAFE_RELEASE(pFilter);
				}
			}
			SAFE_RELEASE(pFilter);
			SAFE_RELEASE(pEnum);
		}	
	}
	return rt;
}
BOOL CFilterControl::SetNewSeekTime(LONGLONG llPTS)
{	
	HRESULT hr = S_OK;
	if(mpCaptionParser)
	{
		ITccCaptionParser* pICaptionParser = NULL;
		hr = mpCaptionParser->QueryInterface(IID_ITccCaptionParser, (void**)&pICaptionParser);
		if( SUCCEEDED(hr) && pICaptionParser)
		{
			pICaptionParser->SetStartTime(llPTS);	
			SAFE_RELEASE(pICaptionParser);
		}
	}
	return SUCCEEDED(hr);
}

BOOL CFilterControl::isNullVideoDec()
{
	HRESULT hr;
	IBaseFilter* NullVideoDec;
	BOOL rt = SUCCEEDED(hr=mpGraph->FindFilterByName(L"TCC NullVideoDec Filter", &NullVideoDec));
	SAFE_RELEASE(NullVideoDec)
	return rt;
}

BOOL CFilterControl::isAudioRender()
{
	HRESULT hr;
	IBaseFilter* AudioRenderer;
	BOOL rt = SUCCEEDED(hr=mpGraph->FindFilterByName(L"Audio Renderer", &AudioRenderer));
	SAFE_RELEASE(AudioRenderer)
	return rt;
}


void CFilterControl::SetPrintInformation(BOOL bPrint)
{
	//printf("[%s] %s Print Information (VPU Decoding Time, VRend Scaling Time)\n", __FUNCTION__, (bPrint)?"Enable":"Disable");	
	if (mpGraph)
	{		
		ITCCPrintScalingInfoInterface* pIPrintScalingInfo;
		IEnumFilters *pEnum = NULL;
		HRESULT hr=mpGraph->EnumFilters(&pEnum);
		if(pEnum && hr==S_OK)
		{
			IBaseFilter *pFilter=NULL;
			ULONG c;
			while( S_OK==pEnum->Next(1, &pFilter, &c) )
			{			
				if(pFilter)
				{		
					hr=pFilter->QueryInterface(IID_ITCCPrintScalingInfo, (void**)&pIPrintScalingInfo);
					if(hr==S_OK && pIPrintScalingInfo )
					{	
						pIPrintScalingInfo->SetPrintScalingInfo(bPrint);		
 						SAFE_RELEASE(pIPrintScalingInfo);				
						break;
					}
 					SAFE_RELEASE(pFilter);
				}
			}			
			SAFE_RELEASE(pFilter);
			SAFE_RELEASE(pEnum);
		}	

		ITCCPrintDecodingInfoInterface* pIPrintDecodingInfo;		
		hr=mpGraph->EnumFilters(&pEnum);
		if(pEnum && hr==S_OK)
		{
			IBaseFilter *pFilter=NULL;
			ULONG c;
			while( S_OK==pEnum->Next(1, &pFilter, &c) )
			{			
				if(pFilter)
				{		
					hr=pFilter->QueryInterface(IID_ITCCPrintDecodingInfo, (void**)&pIPrintDecodingInfo);
					if(hr==S_OK && pIPrintDecodingInfo )
					{	
						pIPrintDecodingInfo->SetPrintDecodingInfo(bPrint);		
						pIPrintDecodingInfo->Release();
						pIPrintDecodingInfo = NULL;						
						break;
					}
					SAFE_RELEASE(pFilter);
				}
			}			
			SAFE_RELEASE(pFilter);
			SAFE_RELEASE(pEnum);
		}	
	}
}

//////////////////////////////////////////////////////////////////////////
void	CFilterControl::SetDefaultPreset()
{
	int i = 0;
	while( i < 8)
	{
		if (m_stVRM[i].Use == 0)
		{
			m_nType = i;		
			m_stVRM[i].Use = TRUE;
			break;
		}
		i+=2;
	}
}
CRect	CFilterControl::GetPresetRect(int nOrder)
{
	CRect rt;
	stVRM stTemp = m_stVRM[m_nType+nOrder];		
	rt.SetRect(stTemp.left, stTemp.top, stTemp.right, stTemp.bottom);	
	return rt;
}
stVRM	CFilterControl::GetPreset(int nOrder)
{
	return m_stVRM[m_nType+nOrder];
}

///////////////////////////////////////////////////////////////////////////////////

void CFilterControl::GetGMCOption(bool *Status)
{
	if (mpGraph)
	{		
		ITCCGetGMCOptionInterface* pITCCGMCOption;
		IEnumFilters *pEnum = NULL;
		HRESULT hr=mpGraph->EnumFilters(&pEnum);
		if(pEnum && hr==S_OK)
		{
			IBaseFilter *pFilter=NULL;
			ULONG c;
			while( S_OK==pEnum->Next(1, &pFilter, &c) )
			{			
				if(pFilter)
				{		
					hr=pFilter->QueryInterface(IID_ITCCGetGMCOption, (void**)&pITCCGMCOption);
					if(hr==S_OK && pITCCGMCOption )
					{	
						pITCCGMCOption->GetGMCStatus(Status);		
 						SAFE_RELEASE(pITCCGMCOption);					
						break;
					}
 					SAFE_RELEASE(pFilter);
				}
			}			
			SAFE_RELEASE(pFilter);
		}		
		SAFE_RELEASE(pEnum);
	}
}

void CFilterControl::GetWeightedPrediction(bool *Status)
{
	if (mpGraph)
	{		
		ITCCGetWeightedPredictionInterface* pITCCWPrediction;
		IEnumFilters *pEnum = NULL;
		HRESULT hr=mpGraph->EnumFilters(&pEnum);
		if(pEnum && hr==S_OK)
		{
			IBaseFilter *pFilter=NULL;
			ULONG c;
			while( S_OK==pEnum->Next(1, &pFilter, &c) )
			{			
				if(pFilter)
				{		
					hr=pFilter->QueryInterface(IID_ITCCGetWeightedPrediction, (void**)&pITCCWPrediction);
					if(hr==S_OK && pITCCWPrediction )
					{	
						pITCCWPrediction->GetWeightedPredictionStatus(Status);		
 						SAFE_RELEASE(pITCCWPrediction);					
						break;
					}
 					SAFE_RELEASE(pFilter);
				}
			}			
			SAFE_RELEASE(pFilter);
		}		
		SAFE_RELEASE(pEnum);
	}
}

void CFilterControl::GetAspectRatio(int *AspectRatio)
{
	if (mpGraph)
	{		
		ITCCGetAspectRatioInterface* pITCCAspectRatio;
		IEnumFilters *pEnum = NULL;
		HRESULT hr=mpGraph->EnumFilters(&pEnum);
		if(pEnum && hr==S_OK)
		{
			IBaseFilter *pFilter=NULL;
			ULONG c;
			while( S_OK==pEnum->Next(1, &pFilter, &c) )
			{			
				if(pFilter)
				{		
					hr=pFilter->QueryInterface(IID_ITCCGetAspectRatio, (void**)&pITCCAspectRatio);
					if(hr==S_OK && pITCCAspectRatio )
					{	
						pITCCAspectRatio->GetAspectRatio(AspectRatio);		
 						SAFE_RELEASE(pITCCAspectRatio);					
						break;
					}
 					SAFE_RELEASE(pFilter);
				}
			}			
			SAFE_RELEASE(pFilter);
		}		
		SAFE_RELEASE(pEnum);
	}
}